/*
 * handle_logon.cpp
 *
 *  Created on: Nov 27, 2013
 *      Author: killerg
 */


#include "robot_deps.h"

#include "share/msg.h"
#include "share/cl_msg.pb.h"
#include "share/json/json.h"
#include "share/util.h"
#include "share/msg_handler.h"
#include "share/patterns.h"

#include "bot.h"

using namespace std;

void handle_lauth(bot_t* robot, cl::LMsg* msg) {
    auto auth = msg->auth();
    if (auth.has_quing()) {
    	robot->stage = EErrorLogon;
    	return;
    }
    assert(auth.has_json());


    auto json = to_json(auth.json());
    if (json["step"] == "auth") {
        if (json["error"] == "success") {
            UTIL_LOG(T, "logon auth ok");

            CREATE_CL_CMSG(CServerList, serverlist);
            serverlist->set_start(0);
            robot->net.send(___msg);
            robot->stage = ELogonGettingList;
        } else if (json["error"] == "passwd") {

        } else if (json["error"] == "needreg") {
            UTIL_LOG(T, "logon auth not exist");

            Json::Value json;
            json["account"] = robot->account->account;
            json["passwd"] = robot->account->passwd;
            json["step"] = "reg";

            CREATE_CL_CMSG(CAuth, auth);
            auth->set_json(to_cstr(json));
            robot->net.send(___msg);
            robot->stage = ELogonRegistering;
        } else if (json["error"] == "other") {
            UTIL_LOG(T, "logon auth passwd err");
            robot->stage = EErrorLogon;
        } else {
            assert(0);
        }
    } else if (json["step"] == "reg") {
        if (json["error"] == "success") {
            UTIL_LOG(T, "logon reg ok");

            Json::Value json;
            json["account"] = robot->account->account;
            json["passwd"] = robot->account->passwd;
            json["step"] = "auth";

            CREATE_CL_CMSG(CAuth, auth);
            auth->set_json(to_cstr(json));
            robot->net.send(___msg);

            robot->stage = ELogonAuthing;
        } else if (json["error"] == "exist") {
            UTIL_LOG(T, "logon reg exist");
            robot->stage = EErrorLogon;
        } else if (json["error"] == "other") {
            robot->stage = EErrorLogon;
        } else {
            assert(0);
        }
    }
}

void handle_lserverlist(bot_t* robot, cl::LMsg* msg) {
    auto serverlist = msg->serverlist();
    int num = serverlist.info_size();
    if (num <= 0) {
        UTIL_LOG(T, "serverlist has not server");
        robot->stage = EErrorLogon;
        return;
    }

    int32_t serverid = -1;
    stringstream ss;

    for (int i=0; i<serverlist.info_size(); ++i) {
        int id = serverlist.info(i).serverid();
        co::EServerStatus status = serverlist.info(i).status();
        string name =  serverlist.info(i).servername();
        ss<<"|"<<serverid;
        if (status == co::ESS_Running && id == 2) {
            serverid = id;
            break;
        }
    }

    if (serverid < 0) {
        robot->stage = EErrorLogon;
        return;
    }

    CREATE_CL_CMSG(CSelect, select);
    select->set_serverid(serverid);
    robot->net.send(___msg);
    UTIL_LOG(T, "send select server");
    robot->stage = ELogonSelecting;
}

void handle_lselect(bot_t* robot, cl::LMsg* msg) {
    auto select = msg->select();

    if (select.error() != cl::ELSE_Ok) {
        robot->stage = EErrorLogon;
        return;
    }
    robot->data.server_addr = fmt_str("%s:%d", select.ip().c_str(), select.port());
    robot->data.playerid = select.playerid();
    robot->data.key = select.key();

    robot->net.disconnect();
    robot->stage = EServerInit;

    UTIL_LOG(T, "select server ok");

}

template<>
struct msg_traits<cl::LMsg> {
    typedef typename cl::LMsg MsgT;
    typedef bot_t SessionT;

    typedef void (*HandlerT)(SessionT*, MsgT*);

    enum {
        MsgID_ARRAYSIZE = cl::LMsgID_ARRAYSIZE,
    };

    static bool is_valid_msgid(int id) {
        return cl::LMsgID_IsValid(id);
    }

    static void init_handlers(HandlerT handlers[]) {
        for (int i = 0; i < MsgID_ARRAYSIZE; ++i)
            handlers[i] = NULL;

        handlers[cl::ID_LAuth] = handle_lauth;
        handlers[cl::ID_LServerList] = handle_lserverlist;
        handlers[cl::ID_LSelect] = handle_lselect;
    }
};

void bot_t::update_lmsg() {
    if (net.is_connected()) {
        auto msg = net.recv<cl::LMsg>();
        while (msg) {
            Singleton<msg_handler_t<cl::LMsg>>::Instance().handle(this, msg);
            delete msg;
            msg = net.recv<cl::LMsg>();
        }
    }
}
